/************************************
 * Package: RGcpp					*
 * Authors: Rui Eduardo Gouveia Gil	*
 * Date: 2010						*
 ************************************/
#ifndef __RGCPP_JOB_H__
#define __RGCPP_JOB_H__

#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>

#include "rgcpp/structs/Map.h"

namespace rgcpp
{

enum JobStatus
{
	JS_WAITING,
	JS_EXECUTING,
	JS_FAIL,
	JS_DONE,
};

class JobScheduler;
class Job
{
	friend class JobScheduler;

	private:
		bool doneExc;
		time_t execTime;
		JobStatus status;
		unsigned int jobId;
		boost::mutex doneMut;
		boost::recursive_mutex mut;
		JobScheduler* jobScheduler;
		boost::shared_ptr<Job> parent;
		boost::condition_variable doneCond;
		Map<unsigned int, boost::shared_ptr<Job> >childs;

	public:
		Job();
		Job(unsigned int offset);
		virtual ~Job();

		void updateExecuteTime(unsigned int offset);

		unsigned int getJobId();
		time_t getExecuteTime();
		JobScheduler* getJobScheduler();
		boost::shared_ptr<Job> getParent();

		JobStatus getStatus() const;
		void setStatus(JobStatus status);

		bool wait(unsigned int timeout);

	protected:
		virtual void execute(){};
		virtual void callBack(boost::shared_ptr<Job> child){};
		virtual void final(){};

		void scheduleChildJob(boost::shared_ptr<Job> child);

	private:
		void setJobId(unsigned int jobId);
		void setParent(boost::shared_ptr<Job> parent);
		void setJobScheduler(JobScheduler* jobScheduler);

		void executeJob();

		void notifyParent(JobStatus status=JS_DONE);

		void addChild(boost::shared_ptr<Job> child);
		bool pendingJobs();
		void childFinish(const unsigned int childJobId);
};

}

#endif
